﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Security.Cryptography;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.RegularExpressions;
using CoreShop.App;
using CoreShop.Library;
using CoreShop.Services;
using System.Windows.Forms;
using CoreShop.Model;
using CoreShop.PrintService;
using SqlSugar;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Rebar;
using Yitter.IdGenerator;
using SqlSugar.Extensions;
using NPOI.SS.Formula.Functions;
using Sunny.UI;
using CoreShop.App.Properties;
using System.Drawing;
using System.ComponentModel.DataAnnotations;
using static CoreShop.Library.GlobalEnumVars;
using System.Threading.Tasks;

namespace CoreShop
{
    public class OrderingUtil
    {
        // 验证方法
        public bool IsValidError(corecmsfoodordering model)
        {
            string errorMsg = "";
            // 1. 创建验证上下文
            var validationContext = new ValidationContext(model);

            // 2. 存储验证结果的集合
            var validationResults = new List<ValidationResult>();

            // 3. 执行验证（validateAllProperties: true 表示验证所有属性）
            bool isValid = Validator.TryValidateObject(
                model,
                validationContext,
                validationResults,
                validateAllProperties: true
            );

            // 4. 处理验证失败的情况
            if (!isValid)
            {
                foreach (var error in validationResults)
                {
                    // 输出错误信息（属性名 + 错误描述）
                    //Console.WriteLine($"属性 {error.MemberNames.FirstOrDefault()}: {error.ErrorMessage}");
                    errorMsg = errorMsg + $"{error.ErrorMessage}" +"\n";
                }
            }
            if (!string.IsNullOrEmpty(errorMsg))
            {
                UIMessageBox.Show(errorMsg, "提示:",UIStyle.Red);
                return false;
            }
            return true;
        }

        /// <summary>
        /// 获取所有挂单数量
        /// </summary>
        /// <param name="custoType"></param>
        /// <returns></returns>
        public async static Task<string> GetHangupsCount()
        {
            var where = Expressionable.Create<corecmsfoodorderingmaster>();
            where = where.And(a => a.deskId == (int)GlobalEnumVars.OrderDeskType.OrderingHangup);
            var mcount = await new corecmsfoodorderingmasterServices().CountAsync(where.ToExpression());
            if (mcount > 0) return mcount.ToString();
            return "";
        }

        /// <summary>
        /// 折扣保存
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public bool UpdateDiscount(corecmsfoodordering entity, DicountInfo dicountInfo)
        {
            try
            {               
                var orderingSrv = new corecmsfoodorderingServices();
                bool result = false;
                var orderingTags = new List<corecmsfoodorderingtag>();
                decimal heValue = 0;
                decimal rowDiscount = 0, rowNewPrice = 0;
                var orderingSelectd = orderingSrv.QueryById(entity.id);               

                var orderingTagNew = new corecmsfoodorderingtag();
                orderingTagNew.detailId = entity.id;
                orderingTagNew.orderId = entity.orderId;
                orderingTagNew.tagType = (int)FoodTag.PriceTag;
                orderingTagNew.tagContent = dicountInfo.Desc;

                switch (dicountInfo.Type)
                {
                    case (int)GlobalEnumVars.DiscountMode.DiscountAll:
                        #region 
                        heValue = (decimal)((float)dicountInfo.Value / 100);
                        var orderingList = orderingSrv.QueryByOrderId(entity.orderId);//整单折扣                    
                        if ((orderingList == null) || (orderingList.Count == 0)) return false;

                        var specIds = orderingList.Select(p => p.foodSpecId);
                        var specList = new corecmsfoodspecServices().AsQueryable().Where(p => specIds.Contains(p.id)).ToList();
                        foreach (var ordering in orderingList)
                        {
                            //if ((modelinfo.dataType == (int)GlobalEnumVars.OrderingDataType.Normal)
                            //|| (modelinfo.dataType == (int)GlobalEnumVars.OrderingDataType.Discount))
                            var specInfo = specList.Find(p => p.id == ordering.foodSpecId);
                            if ((specInfo != null) && (!specInfo.disItem)) continue;
                            if (ordering.dataType != (int)GlobalEnumVars.OrderingDataType.Present)
                            {
                                rowDiscount = heValue;
                                rowNewPrice = ServiceUnits.GetLimitPrice(ordering, ordering.price * rowDiscount, ref rowDiscount);
                                ordering.realPrice = rowNewPrice;
                                ordering.realAmount = CommFunc.GetRowAmount(ordering.amount * rowDiscount, AppConstVars.systemsetup.rowAmountDecimal);
                                ordering.discount = rowDiscount;
                                ordering.allAmount = CommFunc.GetRowAmount(ordering.realAmount + ordering.feedAmount + ordering.taskAmount, AppConstVars.systemsetup.rowAmountDecimal);
                                if (!string.IsNullOrEmpty(dicountInfo.Desc))
                                {
                                    var orderingTag = new corecmsfoodorderingtag();
                                    orderingTag.detailId = ordering.id;
                                    orderingTag.orderId = ordering.orderId;
                                    orderingTag.tagType = (int)FoodTag.PriceTag;
                                    orderingTag.tagContent = dicountInfo.Desc;
                                    orderingTags.Add(orderingTag);
                                }
                            }
                            if (!IsValidError(ordering)) return false;
                        }
                        
                        result = orderingSrv.Change<corecmsfoodordering>().UpdateRange(orderingList);
                        #endregion
                        break;
                    case (int)GlobalEnumVars.DiscountMode.Discount:
                        #region    
                        //if ((orderingSelectd.dataType == (int)GlobalEnumVars.OrderingDataType.Normal)
                        //|| (orderingSelectd.dataType == (int)GlobalEnumVars.OrderingDataType.Discount))
                        if (orderingSelectd.dataType != (int)GlobalEnumVars.OrderingDataType.Present)
                        {
                            heValue = (decimal)((float)dicountInfo.Value / 100);
                            rowNewPrice = ServiceUnits.GetLimitPrice(orderingSelectd, orderingSelectd.price * heValue, ref rowDiscount);

                            orderingSelectd.realPrice = rowNewPrice;
                            orderingSelectd.realAmount = CommFunc.GetRowAmount(orderingSelectd.realPrice * orderingSelectd.quantity, AppConstVars.systemsetup.rowAmountDecimal);
                            orderingSelectd.discount = heValue;
                            orderingSelectd.allAmount = CommFunc.GetRowAmount(orderingSelectd.realAmount + orderingSelectd.feedAmount + orderingSelectd.taskAmount, AppConstVars.systemsetup.rowAmountDecimal);
                            if (!IsValidError(orderingSelectd)) return false;
                            result = orderingSrv.Change<corecmsfoodordering>().Update(a => new corecmsfoodordering()
                            {
                                realPrice = orderingSelectd.realPrice,
                                discount = orderingSelectd.discount,
                                realAmount = orderingSelectd.realAmount,
                                allAmount = orderingSelectd.allAmount,
                            }, a => a.id == entity.id);
                            orderingTags.Add(orderingTagNew);
                        }
                        #endregion
                        break;
                    case (int)GlobalEnumVars.DiscountMode.ReduceAmount:
                        #region
                        //if ((orderingSelectd.dataType == (int)GlobalEnumVars.OrderingDataType.Normal)
                        //|| (orderingSelectd.dataType == (int)GlobalEnumVars.OrderingDataType.Discount))
                        if (orderingSelectd.dataType != (int)GlobalEnumVars.OrderingDataType.Present)
                        {
                            if (orderingSelectd.quantity == 0) return result;
                            heValue = (decimal)((float)dicountInfo.Value);
                            decimal allAmount = orderingSelectd.amount + orderingSelectd.feedAmount + orderingSelectd.taskAmount - heValue;
                            orderingSelectd.allAmount = CommFunc.GetRowAmount(allAmount, AppConstVars.systemsetup.rowAmountDecimal);
                            orderingSelectd.realAmount = CommFunc.GetRowAmount(allAmount - orderingSelectd.feedAmount - orderingSelectd.taskAmount, AppConstVars.systemsetup.rowAmountDecimal);
                            orderingSelectd.realPrice = orderingSelectd.realAmount / orderingSelectd.quantity;
                            if (orderingSelectd.price != 0)
                                orderingSelectd.discount = orderingSelectd.realPrice / orderingSelectd.price;
                            if (!IsValidError(orderingSelectd)) return false;
                            result = orderingSrv.Change<corecmsfoodordering>().Update(a => new corecmsfoodordering()
                            {
                                realPrice = orderingSelectd.realPrice,
                                discount = orderingSelectd.discount,
                                realAmount = orderingSelectd.realAmount,
                                allAmount = orderingSelectd.allAmount,
                            }, a => a.id == entity.id);

                            orderingTags.Add(orderingTagNew);
                        }
                        #endregion
                        break;
                    case (int)GlobalEnumVars.DiscountMode.ChangPrice:
                        #region
                        //if ((orderingSelectd.dataType == (int)GlobalEnumVars.OrderingDataType.Normal)
                        //|| (orderingSelectd.dataType == (int)GlobalEnumVars.OrderingDataType.Discount))
                        if (orderingSelectd.dataType != (int)GlobalEnumVars.OrderingDataType.Present)
                        {
                            heValue = (decimal)((float)dicountInfo.Value);
                            rowNewPrice = ServiceUnits.GetLimitPrice(orderingSelectd, heValue, ref rowDiscount);
                            if (rowNewPrice > orderingSelectd.price)
                            {
                                orderingSelectd.price = rowNewPrice;
                                orderingSelectd.amount = orderingSelectd.quantity * rowNewPrice;
                                orderingSelectd.discount = 1;
                            }

                            orderingSelectd.realPrice = rowNewPrice;
                            orderingSelectd.realAmount = CommFunc.GetRowAmount(orderingSelectd.quantity * rowNewPrice, AppConstVars.systemsetup.rowAmountDecimal);
                            orderingSelectd.sourcePrice = orderingSelectd.realPrice;
                            orderingSelectd.allAmount = CommFunc.GetRowAmount(orderingSelectd.realAmount + orderingSelectd.feedAmount + orderingSelectd.taskAmount, AppConstVars.systemsetup.rowAmountDecimal);
                            if (!IsValidError(orderingSelectd)) return false;
                            result = orderingSrv.Change<corecmsfoodordering>().Update(a => new corecmsfoodordering()
                            {
                                price = orderingSelectd.price,
                                amount = orderingSelectd.amount,
                                realPrice = orderingSelectd.realPrice,
                                discount = orderingSelectd.discount,
                                sourcePrice = orderingSelectd.sourcePrice,
                                realAmount = orderingSelectd.realAmount,
                                allAmount = orderingSelectd.allAmount,
                            }, a => a.id == entity.id);

                            orderingTags.Add(orderingTagNew);
                        }
                        #endregion
                        break;
                }
                if (!string.IsNullOrEmpty(dicountInfo.Desc))
                {
                    new corecmsfoodorderingtagServices().InsertRange(orderingTags);
                }
                entity.price = orderingSelectd.price;
                entity.amount = orderingSelectd.amount;
                entity.realPrice = orderingSelectd.realPrice;
                entity.discount = orderingSelectd.discount;
                entity.sourcePrice = orderingSelectd.sourcePrice;
                entity.realAmount = orderingSelectd.realAmount;
                entity.allAmount = orderingSelectd.allAmount;
                return result;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return false;
            }
        }


        public static void SetDishItemImage(UIDishItem item, corecmsfood food)
        {
            try
            {
                if (!AppConstVars.systemsetup.showFoodImg) return;
                FoodUtil foodUtil = new FoodUtil();
                string imgFileName = "";
                if (AppConstVars.systemsetup.paraPartialModel.locaImgFirst)
                {
                    string locaFileName = foodUtil.GetProductLocaImageFile(food);//本地图片优先
                    if (File.Exists(locaFileName))
                    {
                        imgFileName = locaFileName;
                        //item.Image = System.Drawing.Image.FromFile(locaFileName);
                        using (Image image = Image.FromFile(locaFileName))
                        {
                            // 使用图片，例如显示到PictureBox
                            item.Image = new Bitmap(image); // 创建副本，避免原始图片被锁定
                        }
                        return;
                    }
                }
                if (string.IsNullOrEmpty(food.image) && string.IsNullOrEmpty(imgFileName))
                {
                    string locaFileName = foodUtil.GetProductLocaImageFile(food);//本地图片
                    if (File.Exists(locaFileName))
                    {
                        //item.Image = System.Drawing.Image.FromFile(locaFileName);
                        using (Image image = Image.FromFile(locaFileName))
                        {
                            // 使用图片，例如显示到PictureBox
                            item.Image = new Bitmap(image); // 创建副本，避免原始图片被锁定
                        }
                    }
                    else
                        item.Image = Resources.NoImage;
                    return;
                }

                string rmoFileName = foodUtil.GetProductImageFile(food.image);//后台图片                    
                if ((rmoFileName != null) && !File.Exists(rmoFileName))
                {
                    item.Image = Resources.NoImage;
                    new FoodUtil().DownloadProductImage(food, rmoFileName);
                }
                else
                    item.Image = System.Drawing.Image.FromFile(rmoFileName);
            }
            catch { }
        }

        public int GetMobilePayType(string mPayCode, ref bool isMobelePay,ref int mPayType)
        {
            string mSubStr = mPayCode.Substring(0, 2);
            string mSubStr1 = mPayCode.Substring(0, 1);
            if ((mSubStr == "12") && (mPayCode.Length > 17))
            {
                isMobelePay = true;
                return (int)GlobalEnumVars.Payment.wechatpay;
            }
            else
            if ((mSubStr == "13") && (mPayCode.Length == 18))
            {
                isMobelePay = true;
                return (int)GlobalEnumVars.Payment.wechatpay;
            }
            else if ((mSubStr == "28") && (mPayCode.Length == 18))
            {
                isMobelePay = true;
                return (int)GlobalEnumVars.Payment.alipay;
            }
            else if ((mSubStr1 == "6") && (mPayCode.Length > 20))
            {
                isMobelePay = true;
                return (int)GlobalEnumVars.Payment.bank;
            }
            else if ((mSubStr1 == "6") && (mPayCode.Length == 19))
            {
                isMobelePay = true;
                return (int)GlobalEnumVars.Payment.unionPay;
            }
            return mPayType;// CommFunc.ConvertToInt32(pnlPayName.Tag);
        }

        /// <summary>取生鲜商品编码
        /// 取生鲜商品编码
        /// </summary>
        /// <param name="sNumber"></param>
        /// <returns></returns>
        public bool GetWeighingCode(string sNumber, ref corecmsfoodordering ordering)
        {
            try
            {
                int plu = CommFunc.ConvertToInt32(sNumber.Substring(2, 5));
                var where = Expressionable.Create<corecmsfoodspec>();
                where = where.And(p => p.isDelete == false && p.onLine == true);
                where = where.And(p => p.weighPlu == plu && (p.weighType == (int)GlobalEnumVars.WeighType.Weigh));
                                
                corecmsfoodspec goods = new corecmsfoodspecServices().GetFirst(where.ToExpression());
                if (goods == null) return false;
                decimal quantity = 0;
                decimal amount = 0;
                string sSubStr1 = string.Empty;
                switch (AppConstVars.systemsetup.weighingCodeType)
                {
                    case (int)GlobalEnumVars.WeighingCodeType.CodeAmount13://13位金额码(电子秤识别码+商品PLU)
                        sSubStr1 = sNumber.Substring(7, 5);
                        if (!decimal.TryParse(sSubStr1, out amount))
                        {
                            MessageBox.Show("生鲜条码金额段有问题");
                            return false;
                        }
                        amount = CommFunc.ConvertToDecimal(sSubStr1) / 100;
                        if (goods.posPrice != 0) quantity = amount / goods.posPrice;
                        break;
                    case (int)GlobalEnumVars.WeighingCodeType.CodeWeight13://13位重量码(电子秤识别码+商品PLU)
                        sSubStr1 = sNumber.Substring(7, 5);
                        if (!decimal.TryParse(sSubStr1, out quantity))
                        {
                            MessageBox.Show("生鲜条码金额段有问题");
                            return false;
                        }
                        quantity = CommFunc.ConvertToDecimal(sSubStr1) / 100;
                        amount = quantity * goods.posPrice;
                        break;
                    default: return false;
                }                
                ordering = new corecmsfoodorderingServices().CreateByFoodId(goods.id, quantity, AppConstVars.sysUser.id);
                ordering.amount = amount;
                ordering.realPrice = CommFunc.GetRowAmount(ordering.realPrice, AppConstVars.systemsetup.rowAmountDecimal);
                ordering.realAmount = CommFunc.GetRowAmount(amount, AppConstVars.systemsetup.rowAmountDecimal);
                ordering.allAmount = ordering.realAmount;
                return true;
            }
            catch (Exception ex) { MessageBox.Show(ex.Message, "错误009"); }
            return false;
        }


        /// <summary>
        /// 获取
        /// </summary>
        public string GetFoodSoldout(List<corecmsfoodsoldout> foodSoldouts, corecmsfood food)
        {
            string str = "";
            var foodSoldoutItems = foodSoldouts.Where(p => p.foodId == food.id).ToList();

            if (foodSoldoutItems != null && foodSoldoutItems.Count > 0)
            {
                str = string.Format("剩{0}{1}", CommFunc.FormatDecimal(foodSoldoutItems.Find(p => p.foodSpecId == food.foodSpecId).soldout), food.foodSpecName);
                if (!foodSoldoutItems.Exists(p => p.soldout > 0))
                    food.IsSoldout = true;
            }

            return str;
        }

        /// <summary>
        /// 获取
        /// </summary>
        public string GetFoodDiscount(List<corecmsfoodsoldout> foodSoldouts, corecmsfood food)
        {
            string str = "";
            if (food.isHeft.ObjToBool()) str = "3个优惠";
            //var foodSoldout = foodSoldouts.Find(p => p.foodId == food.id);
            //if (foodSoldout != null)
            //    str = string.Format("剩{0}{1}", CommFunc.FormatDecimal(foodSoldout.soldout), food.foodSpecName);
            return str;
        }
                
        /// <summary>
        /// 执行减免金额
        /// </summary>
        /// <param name="orderingMaster"></param>
        /// <param name="amount"></param>
        /// <param name="freeAmount"></param>
        /// <returns></returns>
        public bool SetOrderingFreeAmount(corecmsfoodorderingmaster orderingMaster,decimal freeAmount)
        {            
            orderingMaster.sumFreeAmount = freeAmount;
            orderingMaster.sumReduceAmount = orderingMaster.sumDiscountAmount + orderingMaster.sumFloorAmount + orderingMaster.sumFreeAmount;
            orderingMaster.sumAllAmount = orderingMaster.sumAllAmount1 - orderingMaster.sumFloorAmount - orderingMaster.sumFreeAmount;
            var bl = new corecmsfoodorderingmasterServices().UpdateAsync(orderingMaster);
            return bl;
        }

        /// <summary>
        /// 是否可以修改
        /// </summary>
        /// <param name="orderingDetail"></param>
        /// <param name="orderingSelected"></param>
        /// <param name="operateType"></param>
        /// <param name="quantity">计划修改后的数量</param>
        /// <returns></returns>
        public bool IsOrderingModify(List<corecmsfoodordering> orderingDetail, corecmsfoodordering orderingSelected,decimal quantity,  int operateType)
        {
            if (orderingSelected.weighType != (int)GlobalEnumVars.WeighType.Default) return true;
            //p.sourceId == ordering.id说明该行已有促销
            var orderingChild = orderingDetail.Find(p => p.sourceId == orderingSelected.id);
            if ((orderingChild != null) && (quantity < orderingChild.quantity))
            {
                string msg = "已有关联的促销订单明细数据,无法修改，请先修改关联的明细。";
                UIMessageBox.Show(msg, "系统提示", UIStyle.Red, UIMessageBoxButtons.OK);
                return false;
            }
            return true;
        }

    }
}
